// -*- mode: c++; indent-tabs-mode: nil; -*-
//
//The Biomolecule Toolkit (BTK) is a C++ library for use in the
//modeling, analysis, and design of biological macromolecules.
//Copyright (C) 2006, Tim Robertson <kid50@users.sourceforge.net>
//
//This program is free software; you can redistribute it and/or modify
//it under the terms of the GNU Lesser General Public License as published
//by the Free Software Foundation; either version 2.1 of the License, or (at
//your option) any later version.
//
//This program is distributed in the hope that it will be useful,  but
//WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//Lesser General Public License for more details.
//
//You should have received a copy of the GNU Lesser General Public License
//along with this program; if not, write to the Free Software Foundation,
//Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#include <ostream>

#include <boost/detail/lightweight_test.hpp>

#include <btk/core/concepts/atom_concept.hpp>
#include <btk/core/atoms/pdb_atom.hpp>

using namespace std;
using namespace BTK;
using BTK::MATH::BTKVector;
using BTK::ATOMS::Atom;
using BTK::ATOMS::PDBAtom;
using BTK::CONCEPTS::AtomConcept;

template <typename AtomType>
void test_atom_concept_fxns()
{
  BTKVector p(1,2,3);
  typedef typename AtomType::atom_id_type atom_id_type;
  typedef typename AtomType::element_id_type element_id_type;
 
  atom_id_type atom_id = 123;
  element_id_type element_id = element_id_type::N();
 
  // test constructors
  {
    AtomType a;
    AtomType a2(p,atom_id,element_id);
    AtomType a3(a2);
  }

  // test type methods
  {
    AtomType a;
    a.set_type(atom_id);
    BOOST_TEST(a.type() == atom_id);

    a.set_element_type(element_id);
    BOOST_TEST(a.element_type() == element_id);
  }

  // test position methods
  {
    AtomType a;
    a.set_position(BTKVector(-1,-1,-1));
    BOOST_TEST(a.position() == BTKVector(-1,-1,-1));
  }

  // test selection methods
  {
    AtomType a;
    a.select();
    BOOST_TEST(a.selected());
    a.select(false);
    BOOST_TEST(!a.selected());
  }

  // test equality comparisons
  {
    AtomType a;
    AtomType b(p,atom_id,element_id);

    BOOST_TEST(a != b);
    BOOST_TEST(!(a == b));

    AtomType b2(b);
    BOOST_TEST(b == b2);
    BOOST_TEST(!(b != b2));
  }
}

int main()
{
  boost::function_requires<AtomConcept<Atom<> > >();
  boost::function_requires<AtomConcept<PDBAtom> >();


  //
  // tests for all objects conforming to AtomConcept
  //
  test_atom_concept_fxns<Atom<> >();
  test_atom_concept_fxns<PDBAtom>();

  //
  // additional tests for PDBAtom
  //
  PDBAtom::chemical_type_system cts;

  PDBAtom pdba(cts,
               false,
               1,
               123,
               ' ',
               456,
               'A',
               1,
               ' ',
               BTKVector(1,1,1),
               1.0,2.0);

  PDBAtom copy(pdba);

  BOOST_TEST(pdba.number() == copy.number() && pdba.number() == 1);
  pdba.set_number(2);
  BOOST_TEST(pdba.number() == 2);

  //  BOOST_TEST(pdba.res_name() == copy.res_name() && pdba.res_name() == "ALA");

  BOOST_TEST(pdba.res_number() == copy.res_number() && pdba.res_number() == 1);
  pdba.set_res_number(2);
  BOOST_TEST(pdba.res_number() == 2);

  BOOST_TEST(pdba.chain_id() == copy.chain_id() && pdba.chain_id() == 'A');
  pdba.set_chain_id('B');
  BOOST_TEST(pdba.chain_id() == 'B');

  BOOST_TEST(pdba.alt_loc() == copy.alt_loc() && pdba.alt_loc() == ' ');
  pdba.set_alt_loc('A');
  BOOST_TEST(pdba.alt_loc() == 'A');

  BOOST_TEST(pdba.insert_code() == copy.insert_code() && pdba.insert_code() ==  ' ');
  pdba.set_insert_code('A');
  BOOST_TEST(pdba.insert_code() == 'A');

  BOOST_TEST(pdba.occupancy() == copy.occupancy() && pdba.occupancy() == 1.0);
  pdba.set_occupancy(0.75);
  BOOST_TEST(pdba.occupancy() == 0.75);

  BOOST_TEST(pdba.b_factor() == copy.b_factor() && pdba.b_factor() == 2.0);
  pdba.set_b_factor(0.8);
  BOOST_TEST(pdba.b_factor() == 0.8);

  return boost::report_errors();
}

